`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date:
// Design Name:
// Module Name: Cordic_XYZ
// Project Name:
// Target Devices:
// Tool Versions:
// Description: ****
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
//x(i+1) = x(i) - y(i) * di * 2^(-i)
//y(i+1) = y(i) + x(i) * di * 2^(-i)
//z(i+1) = z(i) - arctan(di * 2^(-i))
//
//
//
module Cordic_XYZ(
    input  signed [31:0]        i_xi        ,
    input  signed [31:0]        i_yi        ,
    input  signed [31:0]        i_zi        ,
    input         [1:0]         mode        ,//0:圆周旋转, 1:圆周向量, 2:线性旋转, 3:线性向量
    input         [15:0]        i_count     ,

    output signed [31:0]        o_xi_1      ,
    output signed [31:0]        o_yi_1      ,
    output signed [31:0]        o_zi_1      
);

wire               w_di                         ;   
wire signed [31:0] w_arctan[0:15]               ; 

assign w_arctan[0 ] = 450000                    ;
assign w_arctan[1 ] = 265650                    ;
assign w_arctan[2 ] = 140362                    ;
assign w_arctan[3 ] = 71250                     ;
assign w_arctan[4 ] = 35763                     ;
assign w_arctan[5 ] = 17899                     ;
assign w_arctan[6 ] = 8951                      ;
assign w_arctan[7 ] = 4476                      ;
assign w_arctan[8 ] = 2238                      ;
assign w_arctan[9 ] = 1119                      ;
assign w_arctan[10] = 559                       ;
assign w_arctan[11] = 279                       ;
assign w_arctan[12] = 139                       ;
assign w_arctan[13] = 69                        ;
assign w_arctan[14] = 34                        ;
assign w_arctan[15] = 17                        ;

assign w_di = mode[0] == 0 ? (i_zi >= 0 ? 1 : 0) : (i_xi[31]^i_yi[31] ? 1 : 0);           
assign o_xi_1 = mode[1] == 0 ? (w_di ? i_xi - (i_yi >>> i_count) : i_xi + (i_yi >>> i_count)):i_xi;
assign o_yi_1 = (w_di ? i_yi + (i_xi >>> i_count) : i_yi - (i_xi >>> i_count));  
assign o_zi_1 = mode[1] == 0 ? (w_di ? i_zi - w_arctan[i_count]  : i_zi + w_arctan[i_count])
                                :(w_di ? i_zi - (10000 >>> i_count)  : i_zi + (10000 >>> i_count));                             

endmodule
